/*********************************************************************
 *	CGE Model (Center - regions) 
 *
 *	Authors: 
 *		D.B. Nurseitov: C++ code from Pascal code, optimization, MPI.
 *		N.Yu. Borowski: Pascal code, model realization, Nelder-Mid.
 *	Created: 07.11.2010
 *
 *	FIXES:
 *		11.11.2010:	Bcast leader Const.txt file for next series.
 *		15.11.2010:	Stopping rule using time limit.
 *		16.11.2010:	Locale, Y__2 limitation.
 *		24.11.2010:	fix of unsafe sprintf to snprintf; fixed double Stat, Weight underful fp error.
 *		11.02.2011:	fix for NTU cluster.
 *		03.03.2011:	regression added.
 *		29.04.2011:	sensitivity added.
 *
 ********************************************************************/
#include <iostream>
#include <fstream>
#include <list>
#include <ctime>
#include <vector>
#include <cassert>
#include <cfloat>
#include <cmath>
#include <locale>
#include <fenv.h>

#include "mpi.h"
#include <string.h>
#define MaxExtended		LDBL_MAX
//#define _M_M68K		1

typedef double		Real;
typedef double		Extended;
typedef std::string	cstring; 

const int
    MaxCNum = 9456,
    MaxVNum = 4957,
    MaxIdentI = 96;//31

const bool CheckBoxUseLaws = false;		// Use Nelder-Mid or not for regulation.

const double DSPogr = 0.0001;	// 1e-4	Supply and Demand discrepancy arroximation error limit.
const int QPred = 1000;		// The iteration limit for Supply-Demand iterations.
const int TNum = 15;		// loadable. Maximal year (2015).
const int TstatStart = 0;
const int TstatNum = 15;
const int EditInNMiStart = 0;	// Session number, if -1 no session will be.
const double DefaultMaxepsilon = 1e-30;	//1e-30;(Nikolaj)
//==Daniyar.
const int DefaultMaxMNIterations = 100;

const int DefaultMaxLawFilesCycles = 60;

const int DefaultMaxMNSecondsPerSession = 300;

//X=Daniyar.
const bool CheckBoxDispDS = false;		// Supply-Demand debugging.
const bool CheckBoxDispPrices = false;	// Price debugging.
const bool IdentConst = true;
const bool CheckUniq = false;

const int root_rank = 0;
//std::string strWorkDir = "/mnt/Share/daniyar/files";	//TODO: fix this after good connection.!
typedef struct
    {
	long double val;
	int rank;
    } SCriterionRank;
    
typedef struct tcRec
    {
	tcRec(){ C = 0; Cmin = 0; Cmax = 0; ident = 0; };
	cstring Name;
	Real C;
	Real Cmin;
	Real Cmax;
	int ident;	// Daniyar
    } TCRec;

typedef struct tvRec
    {
	cstring Name;
    } TVRec;

const int N1_16 = 17;
const int N0_15 = 16;
const int N0_16 = 17;

//std::string strWorkDir = "/mnt/Share/daniyar/files";	//TODO: fix this after good connection.!

//typedef std::exception	CGEException;

class CGEException : public std::exception
{
private:
    cstring _msg;
public:
    CGEException(const cstring & msg);
    
    CGEException(const char * pchMsg);
    
    virtual ~CGEException() throw();
    
    virtual const char * what() const throw();
};

class TStringList : public std::vector<cstring>
{
public: 
    int IndexOf(const cstring & str) const;
};

// TConstFileArray = Array [1..4] of String;
class TConstFileArray : public std::vector<cstring>
{
public:	
    TConstFileArray();
};

// TStatFileArray = Array [1..17] of String;
class TStatFileArray : public std::vector<cstring>
{
public:	
    TStatFileArray();
};

// TCIN = array [1..MaxCNum] of Double;
class TCIN : public std::vector<Real>
{
public:	
    TCIN();
	
    Extended Norm() const;

    friend std::ostream & operator<<(std::ostream & s, const TCIN & a);
};

// TCINIdent = array [1..MaxIdentI] of Double;
class TCINIdent : public std::vector<Real>
{
	public:	TCINIdent();
};

// TCidentI = Array [1..MaxIdentI+1] of Integer;
class TCidentI : public std::vector<int>
{
	public:	TCidentI();
};

// TCi = array [1..16] of Double;
class TCi : public std::vector<Real>
{
	public:	TCi();
};

// TCij = array [1..16, 1..16] of Double;
class TCij : public std::vector<TCi>
{
	public:	TCij();
};

//  TVijArray = array [0..16] of TCij;
class TVijArray : public std::vector<TCij>
{
	public:	TVijArray();
};

// TCiArray = array [0..15] of TCi;
class TCiArray : public std::vector<TCi>
{
	public:	TCiArray();
};

// TCArray = array [0..15] of Double;
class TCArray : public std::vector<Real>
{
	public:	TCArray();
};

// TViArray = array [0..16] of TCi;
class TViArray : public std::vector<TCi>
{
	public:	TViArray();
};

// TVArray = array [0..16] of Double;
class TVArray : public std::vector<Real>
{
	public:	TVArray();
};

// TVIN = array [1..MaxVNum] of Double;
class TVIN : public std::vector<Real>
{
	public:	TVIN();
};

// TVOUT = array [0..15] of TVIN;
class TVOUT : public std::vector<TVIN>
{
	public:	TVOUT();
};
std::ostream & operator<<(std::ostream & s, const TVOUT & a);

// TV_star = array [0..15] of Double;
class TV_star : public std::vector<Real>
{
	public:	TV_star();
};

// TVSTAT = array [0..15] of TVIN;
class TVSTAT : public std::vector<TVIN>
{
	public:	TVSTAT();
};

// CRec : Array [1..MaxCNum] of TCRec;
class CRecArray : public std::vector<TCRec>
{
	public:	CRecArray();
		
    friend std::ostream & operator<<(std::ostream & s, const CRecArray & a);
};

std::ostream & operator<<(std::ostream & s, const TCIN & a);

std::ostream & operator<<(std::ostream & s, const CRecArray & a);
// Vrec : Array [1..MaxVNum] of TVRec;
class VRecArray : public std::vector<TVRec>
{
	public:	VRecArray();
};

std::ostream & operator<<(std::ostream & s, const VRecArray & a);

// Daniyar.
// Class for correct outputing data.
// Variable name + tab + var0 + tab + var1 + ... + var15 + endl.
class VRecTVOUT
{
	const TVOUT & _tv;
	const VRecArray & _vr;
	public: 
	explicit VRecTVOUT(const TVOUT & tv, const VRecArray & vr) : _tv(tv), _vr(vr){};
	friend std::ostream & operator<<(std::ostream & s, const VRecTVOUT & a);
};
std::ostream & operator<<(std::ostream & s, const VRecTVOUT & a);

void MsgErr(cstring msg);
void MsgInf(cstring msg);
